var entityCollection = require('../../../Base/server/controllers/EntityCollection'),
    _ = require('lodash'),
    Q = require('q'),
    Transaction = require('../../../Base/server/controllers/Transaction'),
    BaseEnum = require('../../../Base/server/controllers/Enum'),
    mongoose = require('mongoose');

// 聚合
exports.aggregate = function(args) {
    var deferred = Q.defer();

    var entity = entityCollection.getEntity("BizRecord");
    entity.Entity.aggregate(args, function(err, result) {
        if (err) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询条码流水错误';
            newErr.message = '查询条码流水错误, 请检查查询参数！';
            deferred.reject(newErr);
            return;
        }
        deferred.resolve(result);
    });

    return deferred.promise;
};
//更新流水信息
exports.updateBizRecordByValue = function(bizRecordId, value, completeFun) {
    var entity = entityCollection.getEntity("BizRecord");
    entity.updateByValue({ _id: bizRecordId }, value, function(err, result) {
        completeFun(err, result);
    });
};

//查找条码的所有流水(按时间降序)
exports.findAllByBarcodeMasterAndWork = function(barcodMasterId, workId, completeFun) {
    var entity = entityCollection.getEntity("BizRecord");
    entity.find({
        BarcodeMaster: barcodMasterId,
        Work: workId
    }, { CollectDateTime: -1 }, null, function(err, record) {
        if (err) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询条码流水错误';
            newErr.message = '请检查查询参数！';
            completeFun(newErr);
        } else {
            completeFun(null, record);
        }
    });
};
//查找条码流水
exports.findByBarcodeMasterAndWork = function(barcodMasterId, workId, completeFun) {
    var entity = entityCollection.getEntity("BizRecord");
    entity.findOne({
        BarcodeMaster: barcodMasterId,
        Work: workId
    }, [{ path: 'Users' }, { path: 'QCUser' }], function(err, record) {
        if (err) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询错误';
            newErr.message = '语法错误，请检查查询参数！';
            completeFun(newErr);
        } else {
            completeFun(null, record);
        }
    });
};
//统计单品工序流水记录数
exports.countBizRecords = function(barcodMasterId, operationId) {
    var deferred = Q.defer();

    var entity = entityCollection.getEntity("BizRecord");
    entity.Entity
        .find({ BarcodeMaster: barcodMasterId, Operation: operationId })
        .count()
        .exec(function(err, num) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询错误';
                newErr.message = '统计单品工序流水记录数错误';
                deferred.reject(newErr);
                return;
            }
            deferred.resolve(num);
        });

    return deferred.promise;
};
//按条件查询流水
exports.findByCondition = function(condition, completeFun) {
    var entity = entityCollection.getEntity("BizRecord");
    entity.findOne(condition, null, function(err, record) {
        if (err) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询错误';
            newErr.message = '语法错误，请检查查询参数！';
            completeFun(newErr);
        } else {
            completeFun(null, record);
        }
    });

};
//创建条码流水
exports.insert = function(bizRecordData, completeFun) {
    var bizRecordEntity = entityCollection.getEntity("BizRecord");
    bizRecordEntity.insert(bizRecordData, function(err, newBizRecord) {
        completeFun(err, newBizRecord);
    });
};
//创建多条条码流水
exports.addBizRecords = function(bizRecords, completeFun) {


    bizRecords.forEach(function(bizRecord) {
        bizRecord.RowStatus = BaseEnum.RowStatus.Insert.Value;
        bizRecord.CreatedBy = bizRecord.QCUser;
    });

    writeBizRecords(bizRecords).then(function(result) {
        completeFun(null, result);
    }, function(err) {
        var newErr = new Error();
        newErr.leval = 9;
        newErr.title = '创建流水记录失败';
        newErr.message = '';
        completeFun(newErr);

    });

};

exports.findByPeriodOutput = function(bizRecordId){
    var entity = entityCollection.getEntity("BizRecord");

    return new Promise(function(resolve, reject){
        
        entity.findOne({ _id: bizRecordId }, [{
                path: 'BarcodeMaster',
                select: 'Operation ItemMaster Specification BarcodeType QCReworkOperation DescSeg1 DescSeg2 DescSeg3',
                populate: {
                    path: 'Operation',
                    select: 'IsTiming',
                    model: 'Operation'
                }
            }, { path: 'WorkLocation', select: 'Department' }],
            function(err, bizRecord) {
                if(err){
                    reject(err);
                }
                else{
                    resolve(bizRecord);
                }
            }
        );
    });
};

function writeBizRecords(bizRecords) {
    var deferred = Q.defer();

    Transaction.BatchSaveByTran([
            { EntityName: 'BizRecord', Records: bizRecords }
        ],
        function(err, result) {
            if (err) {
                deferred.reject(err);
                return;
            }
            deferred.resolve(result);
        }
    );

    return deferred.promise;
}

//删除条码流水
exports.deleteById = function(bizRecordId, completeFun) {
    var bizRecordEntity = entityCollection.getEntity("BizRecord");
    bizRecordEntity.deleteById(bizRecordId, function(err, result) {
        completeFun(err, result);
    });
};

// 查找单品所有流水
exports.findByBarcodeMaster = function(barcodeMasterIds, completeFun) {
    var entity = entityCollection.getEntity("BizRecord");
    entity.find({ BarcodeMaster: { $in: barcodeMasterIds } }, { CollectDateTime: 1 }, [{
        path: 'Users',
        select: 'Code Name'
    }, {
        path: 'Operation'
    }, {
        path: 'WorkLocation',
        select: 'Code Name Department',
        populate: {
            path: 'Department',
            select: 'Code Name',
            model: 'Department'
        }
    }], function(err, records) {
        if (err) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询错误';
            newErr.message = '语法错误，请检查查询参数！';
            completeFun(newErr);
        } else {
            completeFun(null, records);
        }
    });
};

// 仅供压力测试使用：更新一条条码流水记录
exports.updateOneST = function(barcodMasterId, completeFun) {
    var entity = entityCollection.getEntity("BizRecord");
    entity.findOne({ BarcodeMaster: barcodMasterId }, null, function(err, record) {
        if (err || !record) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询错误';
            newErr.message = '语法错误，请检查查询参数！';
            completeFun(newErr);
            return;
        }
        record.BusinessStatus = 1;
        entity.update(record, function(err, modifyRecord) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询错误';
                newErr.message = '语法错误，请检查查询参数！';
                completeFun(newErr);
                return;
            }
            completeFun(null, modifyRecord);
        });
    });
};

// 根据工位查询最近一条流水档记录
exports.findNearestRecord = function(workLocationId) {
    var deferred = Q.defer();

    var entity = entityCollection.getEntity("BizRecord");
    entity.Entity
        .find({ WorkLocation: workLocationId })
        .sort({ CollectDateTime: -1 })
        .limit(1)
        .exec(function(err, records) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询错误';
                newErr.message = '语法错误，请检查查询参数！';
                deferred.reject(newErr);
                return;
            }
            deferred.resolve(records);
        });

    return deferred.promise;
}

//首页-质量预警
exports.qualityWaring = function(completeFun) {
    mapReduceByDate().then(function(results) {
        completeFun(null, results);
    }, function(err) {
        completeFun(err);
    });
};

//按时间分组查找流水档
function mapReduceByDate() {
    var deferred = Q.defer();
    var entity = entityCollection.getEntity("BizRecord");
    var barcodeMap = function() {
        var date = this.CollectDateTime;
        var year = date.getFullYear();
        var month = date.getMonth();
        var day = date.getDate();
        var key = year + "-" + (month + 1) + "-" + day;
        emit(key, { bizRecords: [this] });
    };
    var barcodeReduce = function(key, values) {
        var res = {
            bizRecords: []
        };
        values.forEach(function(val) {
            val.bizRecords.forEach(function(obj) {
                res.bizRecords.push(obj);
            });
        });
        return res;
    };

    var barcodeQuery = {
        QCStatus: 1
    };

    var option = {
        map: barcodeMap,
        reduce: barcodeReduce,
        sort: { CollectDateTime: 1 },
        query: barcodeQuery
    };
    entity.mapReduce(option, function(err, results) {
        if (err) {
            deferred.reject(err);
        } else {
            var localArray = [],
                batches = [];
            _.forEach(results, function(result) {
                batches.push(diyPopulateBarcodeMaster(result, localArray));
            });
            Q.all(batches).then(function() {
                deferred.resolve(localArray);
            }, function() {
                deferred.reject();
            });
        }
    });

    return deferred.promise;
}

function diyPopulateBarcodeMaster(result, localArray) {
    var deferred = Q.defer();
    var barcodeModel = mongoose.model('BarcodeMaster');
    barcodeModel.populate(result.value.bizRecords, { path: 'BarcodeMaster' }, function(err, resultsBarcodes) {
        if (err) {
            deferred.reject(err);
        } else {
            diyPopulateUser(resultsBarcodes).then(function(record) {
                localArray.push({ key: result._id, data: record });
                deferred.resolve(localArray);
            }, function() {
                deferred.reject();
            });
        }
    });

    return deferred.promise;
}

function diyPopulateUser(resultsBarcodes) {
    var deferred = Q.defer();
    var userModel = mongoose.model('User');
    userModel.populate(resultsBarcodes, { path: 'Users' }, function(err, userResult) {
        if (err) {
            deferred.reject(err);
        } else {
            diyPopulateWorkLocation(userResult).then(function(workLocation) {
                deferred.resolve(workLocation);
            }, function() {
                deferred.reject();
            });
        }
    });

    return deferred.promise;
}

function diyPopulateWorkLocation(userResult) {
    var deferred = Q.defer();
    var workLocationModel = mongoose.model('WorkLocation');
    workLocationModel.populate(userResult, {
        path: 'WorkLocation',
        populate: [{
            path: 'Department',
            select: 'Code Name',
            model: 'Department'
        }]
    }, function(err, workLocation) {
        if (err) {
            deferred.reject(err);
        } else {
            deferred.resolve(workLocation);
        }
    });
    return deferred.promise;

}

//根据工位和日期查找流水
// exports.queryByDateAndWorkLocation = function (date, workLocation, completeFun) {

//     var entity = entityCollection.getEntity("BizRecord");
//     entity.find({WorkLocation:workLocation, 

//         CollectDateTime:{$gte:date+" 00:00:00",$lte:date+" 23:59:59"}},
//         {CollectDateTime: -1}
//         , [{
//         path: "BarcodeMaster",
//         select: "ItemMasterCode"
//     }], function (err, records) {
//         if (err) {
//             var newErr = new Error();
//             newErr.leval = 9;
//             newErr.title = '查询错误';
//             newErr.message = '查询流水表失败！';
//             completeFun(newErr);
//         } else {
//             completeFun(null, records);
//         }
//     });
// };

//根据工位和日期查找流水
exports.queryByDateAndWorkLocation = function(date, workLocation, completeFun) {
    mapReduceByBarcodeMaster(date, workLocation).then(function(results) {
        completeFun(null, results);
    }, function(err) {
        completeFun(err);
    });
};

//按条码主档分组查找流水档
function mapReduceByBarcodeMaster(date, workLocation) {
    var deferred = Q.defer();
    var entity = entityCollection.getEntity("BizRecord");
    var barcodeMap = function() {
        emit(this.BarcodeMaster, { bizRecords: [this] });
    };

    var barcodeReduce = function(key, values) {
        var res = {
            bizRecords: []
        };
        values.forEach(function(val) {
            val.bizRecords.forEach(function(obj) {
                res.bizRecords.push(obj);
            });
        });
        return res;
    };

    var barcodeQuery = {
        WorkLocation: workLocation,
        CollectDateTime: { $gte: date + " 00:00:00", $lte: date + " 23:59:59" }
    };

    var option = {
        map: barcodeMap,
        reduce: barcodeReduce,
        sort: { CollectDateTime: 1 },
        query: barcodeQuery
    };
    entity.mapReduce(option, null, null, function(err, results) {
        if (err) {
            deferred.reject(err);
        } else {
            var localArray = [],
                batches = [];
            _.forEach(results, function(result) {
                batches.push(getPopulateBarcodeMaster(result, localArray));
            });
            Q.all(batches).then(function() {
                deferred.resolve(localArray);
            }, function() {
                deferred.reject();
            });
        }
    });


    return deferred.promise;
}
//查询条码主档的关联表
function getPopulateBarcodeMaster(result, localArray) {
    var deferred = Q.defer();
    var barcodeModel = mongoose.model('BarcodeMaster');
    barcodeModel.populate(result.value.bizRecords, { path: 'BarcodeMaster', select: "ItemMasterCode" }, function(err, resultBarcodeMaster) {
        if (err) {
            deferred.reject(err);
        } else {
            //取初次时间的流水
            if (resultBarcodeMaster[0] && resultBarcodeMaster[0].BarcodeMaster) {
                localArray.push(resultBarcodeMaster[0]);
            }
            deferred.resolve(localArray);

        }
    });

    return deferred.promise;
}
